package com.kensure.shike.order.service;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.annotation.Resource;

import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import co.kensure.exception.BusinessExceptionUtil;
import co.kensure.frame.JSBaseService;
import co.kensure.mem.ArithmeticUtils;
import co.kensure.mem.CollectionUtils;
import co.kensure.mem.DateUtils;
import co.kensure.mem.MapUtils;
import co.kensure.mem.NumberUtils;
import co.kensure.mem.PageInfo;
import co.kensure.mem.Utils;

import com.kensure.basekey.BaseKeyService;
import com.kensure.mycom.config.service.MyConfigService;
import com.kensure.shike.baobei.service.SKBaobeiService;
import com.kensure.shike.card.model.CardUser;
import com.kensure.shike.card.service.CardUserService;
import com.kensure.shike.order.dao.SKFinPayDao;
import com.kensure.shike.order.model.SKFinPay;
import com.kensure.shike.order.model.SKOrder;
import com.kensure.shike.order.model.SKZffs;
import com.kensure.shike.order.query.SKFinPayQuery;
import com.kensure.shike.user.model.SKUser;
import com.kensure.shike.user.model.SKUserSJYue;
import com.kensure.shike.user.service.SKUserFRService;
import com.kensure.shike.user.service.SKUserSJYueService;
import com.kensure.shike.user.service.SKUserService;
import com.kensure.shike.weixin.service.WeixinXiaoChengXuService;
import com.kensure.shike.weixinpay.model.WXPayinfo;
import com.kensure.shike.zhang.model.SKUserZhang;
import com.kensure.shike.zhang.service.SKUserZhangService;

/**
 * 订单支付情况 服务实现类
 * 
 * @author fankd created on 2019-7-6
 * @since
 */
@Service
public class SKFinPayService extends JSBaseService {

	@Resource
	private SKFinPayDao dao;
	@Resource
	private BaseKeyService baseKeyService;
	@Resource
	private SKOrderService sKOrderService;
	@Resource
	private SKUserService sKUserService;
	@Resource
	private SKBaobeiService sKBaobeiService;
	@Resource
	private SKUserZhangService sKUserZhangService;
	@Resource
	private SKUserFRService sKUserFRService;
	@Resource
	private CardUserService cardUserService;
	@Resource
	private SKFinPayASyncService sKFinPayASyncService;
	@Resource
	private SKUserSJYueService sKUserSJYueService;

	public SKFinPay selectOne(Long id) {
		return dao.selectOne(id);
	}

	public List<SKFinPay> selectByIds(Collection<Long> ids) {
		return dao.selectByIds(ids);
	}

	public List<SKFinPay> selectByWhere(Map<String, Object> parameters) {
		return dao.selectByWhere(parameters);
	}

	public long selectCountByWhere(Map<String, Object> parameters) {
		return dao.selectCountByWhere(parameters);
	}

	public boolean insert(SKFinPay obj) {
		super.beforeInsert(obj);
		obj.setId(baseKeyService.getKey("sk_finpay"));
		Date now = new Date();
		String code = DateUtils.format(now, DateUtils.DATE_FORMAT1) + Utils.randomSMSCode();
		obj.setCode(code);

		if (obj.getYouhui() == null) {
			obj.setYouhui(0D);
		}
		obj.setWxyue(0D);
		obj.setYue(0D);
		obj.setJinbi(0D);
		obj.setDbyue(0D);
		obj.setStatus(0);
		obj.setIsfenrun(0);
		obj.setFkop(0);
		return dao.insert(obj);
	}

	public boolean update(SKFinPay obj) {
		super.beforeUpdate(obj);
		return dao.update(obj);
	}

	public boolean updateByMap(Map<String, Object> params) {
		return dao.updateByMap(params);
	}

	public boolean delete(Long id) {
		return dao.delete(id);
	}

	public boolean deleteMulti(Collection<Long> ids) {
		return dao.deleteMulti(ids);
	}

	public boolean deleteByWhere(Map<String, Object> parameters) {
		return dao.deleteByWhere(parameters);
	}

	/**
	 * 前端，根据用户获取订单
	 */
	public List<SKFinPay> qdlist(Integer status) {
		SKUser user = sKUserService.getUser();
		Map<String, Object> parameters = MapUtils.genMap("userid", user.getId(), "orderby", "id desc");
		if (status != null) {
			if (status == 4) {
				List<SKOrder> orderlist = sKOrderService.selectByStatus(1, user.getId());
				if (CollectionUtils.isEmpty(orderlist)) {
					return null;
				}
				Set<Long> idlist = new HashSet<>();
				for (SKOrder order : orderlist) {
					idlist.add(order.getFinpayid());
				}
				parameters.put("idlist", idlist);
			} else {
				// 不是退货
				parameters.put("status", status);
			}
		}
		List<SKFinPay> list = selectByWhere(parameters);
		setOrderList(list);
		return list;
	}

	/**
	 * 后端，获取订单
	 * 
	 * @param obj
	 * @return
	 */
	public List<SKFinPay> hdlist(SKFinPayQuery query, PageInfo page) {
		Map<String, Object> parameters = setParams(query);
		parameters.put("orderby", "id desc");
		MapUtils.putPageInfo(parameters, page);
		List<SKFinPay> list = selectByWhere(parameters);
		setOrderList(list);
		return list;
	}

	/**
	 * 后端,hdlist计算数量
	 * 
	 * @param obj
	 * @return
	 */
	public Long hdlistCount(SKFinPayQuery query) {
		Map<String, Object> parameters = setParams(query);
		long count = selectCountByWhere(parameters);
		return count;
	}

	/**
	 * 商家端，获取订单
	 * 
	 * @param obj
	 * @return
	 */
	public List<SKFinPay> sjlist(SKFinPayQuery query, PageInfo page) {
		Map<String, Object> parameters = setParams(query);
		parameters.put("orderby", "id desc");
		MapUtils.putPageInfo(parameters, page);
		List<SKFinPay> list = selectByWhere(parameters);
		setOrderList(list);
		return list;
	}

	/**
	 * 商家端,hdlist计算数量
	 * 
	 * @param obj
	 * @return
	 */
	public Long sjlistCount(SKFinPayQuery query) {
		Map<String, Object> parameters = setParams(query);
		long count = selectCountByWhere(parameters);
		return count;
	}

	/**
	 * 设置后端数据
	 * 
	 * @param query
	 * @return
	 */
	private Map<String, Object> setParams(SKFinPayQuery query) {
		Map<String, Object> parameters = MapUtils.bean2Map(query, true);
		if (query.getStatus() != null && query.getStatus() == -100) {
			parameters.remove("status");
			List<SKOrder> orderlist = sKOrderService.selectByStatus(1);
			if (CollectionUtils.isEmpty(orderlist)) {
				parameters.put("status", -1000);
				return parameters;
			}
			Set<Long> idlist = new HashSet<>();
			for (SKOrder order : orderlist) {
				idlist.add(order.getFinpayid());
			}
			parameters.put("idlist", idlist);
		}
		return parameters;
	}

	/**
	 * 设置明细
	 * 
	 * @param finpay
	 */
	private void setOrderList(List<SKFinPay> list) {
		if (CollectionUtils.isNotEmpty(list)) {
			for (SKFinPay finpay : list) {
				setOrderList(finpay);
				finpay.setUser(sKUserService.selectOne(finpay.getUserid()));
			}
		}
	}

	/**
	 * 设置明细
	 * 
	 * @param finpay
	 */
	private void setOrderList(SKFinPay finpay) {
		List<SKOrder> orderlist = sKOrderService.selectByFinpay(finpay.getId());
		finpay.setOrderList(orderlist);
		int dd_close_time = NumberUtils.parseInteger(MyConfigService.getMyConfig("dd_close_time").getVal(), 15);
		// 显示关闭时间
		if (finpay.getStatus() == 0) {
			long p = (new Date()).getTime() - finpay.getCreatedTime().getTime();
			p = dd_close_time - p / 1000 / 60;
			String closeRemark = "订单已关闭";
			if (p > 0) {
				closeRemark = "订单将在" + p + "分钟后关闭";
			}
			finpay.setCloseRemark(closeRemark);
		}
	}

	/**
	 * 根据订单id获取订单详情
	 * 
	 * @param orderidList
	 * @return
	 */
	public SKFinPay detail(Long id) {
		SKFinPay finpay = selectOne(id);
		setOrderList(finpay);
		return finpay;
	}

	/**
	 * 生成订单
	 * 
	 * @param orderidList
	 * @return
	 */
	@Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
	public SKFinPay add(SKFinPay finpay) {
		SKUser user = sKUserService.getUser();
		
		sKUserService.updatePhoneAndName(user.getId(), finpay.getSjphone(), finpay.getSjrname());
		SKFinPay obj = preView(finpay.getOrderList(), user, false);
		obj.setSheng(finpay.getSheng());
		obj.setShi(finpay.getShi());
		obj.setXian(finpay.getXian());
		obj.setSjphone(finpay.getSjphone());
		obj.setSjrname(finpay.getSjrname());
		String peisong = sKOrderService.peisong(finpay.getOrderList());
		obj.setPeisong(peisong);
		insert(obj);
		// 插入从表
		sKOrderService.adds(obj.getOrderList(), obj);
		if (StringUtils.isNotBlank(obj.getYouhuiid())) {
			cardUserService.useCard(NumberUtils.parseLong(obj.getYouhuiid(), null));
		}
		// 生成二维码
		WeixinXiaoChengXuService.genOrderUrl(obj.getId());
		return obj;
	}

	// 预览订单
	public SKFinPay preView(List<SKOrder> orderList, SKUser user, boolean isfree) {
		sKOrderService.preView(orderList, user, isfree);

		SKFinPay finpay = new SKFinPay();
		Double total = 0D;
		Integer bbnum = 0;
		for (SKOrder order : orderList) {
			total = ArithmeticUtils.add(total, order.getTotal());
			bbnum += order.getBbnum();
			order.setTuihuan(order.getTotal());
			finpay.setSjid(order.getSjid());
		}
		finpay.setBbnum(bbnum);
		finpay.setLeiji(total);
		finpay.setYouhui(0D);
		finpay.setUserid(user.getId());
		finpay.setOrderList(orderList);

		List<CardUser> cardlist = cardUserService.selectCanUse(user.getId(), finpay.getLeiji());
		if (CollectionUtils.isNotEmpty(cardlist)) {
			CardUser card = cardlist.get(0);
			finpay.setYouhui(card.getJian());
			finpay.setYouhuiid(card.getId() + "");
			Double t = ArithmeticUtils.sub(finpay.getLeiji(), finpay.getYouhui());
			finpay.setTotal(t);
			finpay.setCard(card);
		} else {
			finpay.setTotal(total);
		}

		return finpay;
	}

	/**
	 * 前端，确认收货
	 */
	public void shouhuo(Long id) {
		SKFinPay one = selectOne(id);
		one.setStatus(99);
		one.setShTime(new Date());
		update(one);
	}

	/**
	 * 前端，关闭订单
	 */
	@Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
	public void close(Long id) {
		SKFinPay one = selectOne(id);
		if (one.getStatus() < 0) {
			BusinessExceptionUtil.threwException("该订单无法关闭");
		}
		one.setStatus(-1);
		update(one);
	}

	/**
	 * 定时器，关闭订单
	 */
	@Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
	public void close() {
		Date now = new Date();
		// 超过15分钟未付款的，进行关闭
		int dd_close_time = NumberUtils.parseInteger(MyConfigService.getMyConfig("dd_close_time").getVal(), 15);
		now = DateUtils.getPastMin(now, -dd_close_time);
		Map<String, Object> parameters = MapUtils.genMap("status", 0, "endCreatedTime", now, "orderby", "id");
		List<SKFinPay> list = selectByWhere(parameters);
		if (CollectionUtils.isNotEmpty(list)) {
			for (SKFinPay finpay : list) {
				close(finpay.getId());
			}
		}
	}

	/**
	 * 定时器，默认确认收货
	 */
	@Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
	public synchronized void queren() {
		Date now = new Date();
		// 订单确认收货时间
		int dd_queren_time = NumberUtils.parseInteger(MyConfigService.getMyConfig("dd_queren_time").getVal(), 10);
		now = DateUtils.getPastDay(now, -dd_queren_time);
		Map<String, Object> parameters = MapUtils.genMap("status", 19, "endFhTime", now, "orderby", "id");
		List<SKFinPay> list = selectByWhere(parameters);
		if (CollectionUtils.isNotEmpty(list)) {
			for (SKFinPay finpay : list) {
				shouhuo(finpay.getId());
			}
		}
	}

	/**
	 * 后端设置快递单号
	 * 
	 * @param obj
	 * @return
	 */
	@Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
	public void kddh(Long id, String kddh) {
		SKFinPay order = selectOne(id);
		order.setKddh(kddh);
		order.setFhTime(new Date());
		order.setStatus(19);
		update(order);
	}

	/**
	 * 用户支付订单成功，返回支付订，同时入账
	 */
	@Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
	public synchronized void weiXinPay(WXPayinfo info) {
		SKFinPay finpay = selectOne(NumberUtils.parseLong(info.getOrderid(), null));
		if (finpay.getStatus() < 1) {
			finpay.setStatus(1);
			finpay.setFkid(info.getId());
			finpay.setFkTime(new Date());
			finpay.setWxyue(finpay.getTotal());
			update(finpay);
			// 消费记账
			addZhang(finpay);
		}
	}

	/**
	 * // 分润预先计算
	 */
	@Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
	public synchronized void testFr(Long id) {
		SKFinPay finpay = selectOne(id);
		// 分润预先计算
		sKUserFRService.addFinpayFr(finpay);
	}

	/**
	 * 付款成功后，进行的操作
	 */
	@Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
	public synchronized void fkop(SKFinPay finpay) {
		// 分润预先计算
		sKUserFRService.addFinpayFr(finpay);
		finpay.setFkop(1);
		update(finpay);
		// 自送，进入确认收货状态
		if ("zs".equals(finpay.getPeisong())) {
			kddh(finpay.getId(), "自送");
		} else if ("zt".equals(finpay.getPeisong())) {
			// 自提，进入完成交易状态
			kddh(finpay.getId(), "自提");
			shouhuo(finpay.getId());
		}
		// 代金券,如果是代金券，需要增加代金券余额
		sKOrderService.addDjq(finpay.getId());
		// 增加销量
		sKOrderService.addXiaoLiang(finpay.getId());

	}

	/**
	 * 付款成功后，进行的操作
	 */
	@Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
	public synchronized void fkop() {
		Map<String, Object> parameters = MapUtils.genMap("startStatus", 1, "fkop", 0, "orderby", "id");
		List<SKFinPay> list = selectByWhere(parameters);
		if (CollectionUtils.isEmpty(list)) {
			return;
		}
		for (SKFinPay finpay : list) {
			fkop(finpay);
		}
	}

	/**
	 * 消费记帐
	 * 
	 * @param obj
	 * @return
	 */
	@Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
	private void addZhang(SKFinPay order) {
		SKUserZhang obj = new SKUserZhang();
		obj.setBusiid(order.getId());
		obj.setBusitypeid(1);
		obj.setYue(order.getYue());
		obj.setDbyue(order.getDbyue());
		obj.setWxyue(order.getWxyue());
		obj.setJinbi(order.getJinbi());
		obj.setUserid(order.getUserid());
		obj.setRemark("消费支出");
		sKUserZhangService.add(obj);
		sKUserZhangService.commit(obj.getId());
		order.setZhangid(obj.getId());
		update(order);
	}

	/**
	 * 根据用户和订单id 获取支付方式
	 */
	@Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
	public SKZffs getZffs(Long id) {
		SKUser user = sKUserService.getUser();
		SKFinPay finpay = detail(id);
		if (user.getId().compareTo(finpay.getUserid()) != 0) {
			BusinessExceptionUtil.threwException("订单信息有误");
		}
		Double dbyue = 0D;
		SKUserSJYue sjyue = sKUserSJYueService.selectByUseridAndSjid(finpay.getUserid(), finpay.getSjid());
		if (sjyue != null) {
			dbyue = sjyue.getYue();
		}
		List<SKOrder> list = finpay.getOrderList();
		for (SKOrder order : list) {
			if (order.getDjqse() > 0) {
				dbyue = 0D;
			}
		}
		SKUser u = sKUserService.selectOneHaveYue(user.getId());
		SKZffs zffs = new SKZffs();
		zffs.setDbyue(dbyue);
		zffs.setYue(u.getYue().getYue());
		return zffs;
	}

	/**
	 * 支付余额扣款
	 */
	@Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
	public synchronized void payYue(Long id, Double money, Integer type) {
		if (money <= 0) {
			BusinessExceptionUtil.threwException("金额数据异常");
		}
		SKZffs zffs = getZffs(id);
		SKFinPay finpay = detail(id);
		if (finpay.getStatus() < 1) {
			finpay.setStatus(1);
			finpay.setFkTime(new Date());
			if (type == 3) {
				if (money.compareTo(zffs.getDbyue()) > 0) {
					BusinessExceptionUtil.threwException("代金券余额不足");
				}
				sKUserSJYueService.updateYue(finpay.getUserid(), finpay.getSjid(), -money);
				finpay.setDbyue(money);
				// 标记分润金额
				sKOrderService.djqfr(finpay.getOrderList());
			} else if (type == 2) {
				finpay.setYue(money);

			}
			// 消费记账
			addZhang(finpay);
			update(finpay);
		} else {
			BusinessExceptionUtil.threwException("请不要重复付款");
		}
	}

	/**
	 * 赠送商品
	 * 
	 * @return
	 */
	@Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
	public void zengsong(Long bbid, String yanse, Long userid) {
		List<SKOrder> orderList = new ArrayList<>();
		SKOrder order = new SKOrder();
		order.setBbid(bbid);
		order.setYanse(yanse);

		orderList.add(order);

		SKUser user = sKUserService.selectOne(userid);

		SKFinPay obj = preView(orderList, user, true);
		obj.setSjphone(user.getPhone());
		obj.setSjrname(user.getRealname());
		insert(obj);
		// 插入从表
		sKOrderService.adds(obj.getOrderList(), obj);
		// 生成二维码
		WeixinXiaoChengXuService.genOrderUrl(obj.getId());
		
		obj.setStatus(1);
		update(obj);
		fkop();
	}
}
